package m3f.io;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;

import m3f.matrix.SparseVector;

public class BinaryMatrixReader extends MatrixReader{
	
	private String filename;
	private int matrixRows;
	private int matrixColumns;
	private DataInputStream file;
	private int readLines;

	@Override
	public void start(String filename) {
		this.filename = filename;
		long start = System.currentTimeMillis();
		try{
			DataInputStream in = new DataInputStream(new
		            BufferedInputStream(new FileInputStream(filename)));
			matrixRows = 0;
			matrixColumns = 0;
			while(true){
				int columns = in.readInt();
				for(int i = 0; i < columns; i++){
					int key = in.readInt();
					in.readDouble();
					if(key >= matrixColumns) matrixColumns = key+1;
				}
				matrixRows++;
			}
		}catch(EOFException ex){
			System.out.println(matrixRows + " vectors with " + matrixColumns + " dimensions in " + filename
					+ " ( "+(System.currentTimeMillis()-start)+" ms )");
			file = null;
		}catch(IOException ex){
			ex.printStackTrace();
		}
	}

	@Override
	public int getMatrixRows() {
		return matrixRows;
	}

	@Override
	public int getMatrixColumns() {
		return matrixColumns;
	}

	@Override
	public ArrayList<SparseVector> readVectors(int lines) {
		ArrayList<SparseVector> vectors = new ArrayList<SparseVector>();
		long start = System.currentTimeMillis();
		int batchCounter = 0;
		try{
			if(file == null){
				file = new DataInputStream(new
		            BufferedInputStream(new FileInputStream(filename)));
				readLines = 0;
			}
			while(batchCounter < lines){
				int columns = file.readInt();
				SparseVector v = new SparseVector();
				for(int i = 0; i < columns; i++){
					v.setQuick(file.readInt(), file.readDouble());
				}
				if(normalizing()) v.normalizeL1();
				vectors.add(v);
				batchCounter++;
				readLines++;
			}
			if(readLines == matrixRows){
				closeFile();
			}
		}catch(EOFException ex){
			closeFile();
		}catch(IOException ex){
			ex.printStackTrace();
		}
		//System.out.println(batchCounter + " vectors read from " + filename + " ( "+(System.currentTimeMillis()-start)+" ms )");
		return vectors;
	}
	
	private void closeFile(){
		try{
			file.close();
			file = null;
			//System.out.println(" Closing File");
		}catch(Exception e){
			e.printStackTrace();
		}		
	}
}
